package com.jeady.timetodo.services

import android.app.AlarmManager
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Binder
import android.os.Build
import android.os.IBinder
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.rememberUpdatedState
import androidx.room.Room
import com.jeady.timetodo.TaskReceiver
import com.jeady.timetodo.activities.MainActivity
import com.jeady.timetodo.activities.task.TaskDetailActivity
import com.jeady.timetodo.activities.task.TaskType
import com.jeady.timetodo.activities.task.runningFlag
import com.jeady.timetodo.base.showToast
import com.jeady.timetodo.database.AppDatabase
import com.jeady.timetodo.database.Task
import com.jeady.timetodo.manager.createNotification
import com.jeady.timetodo.manager.runningServiceChannelId
import com.jeady.timetodo.manager.sendNotification
import com.jeady.timetodo.manager.taskChannelId
import com.jeady.timetodo.utils.TimeToDoAction
import com.jeady.timetodo.utils.currentTime
import com.jeady.timetodo.utils.currentTimestamp
import com.jeady.timetodo.utils.timeFormat
import com.jeady.timetodo.utils.timestampAfter
import kotlin.concurrent.thread

const val runningTaskServiceId = 1
class RunningService: Service() {
    private val TAG: String = "[RunningService]"
    private var taskBroadcast: BroadcastReceiver? = null
    private val taskList = mutableStateListOf<Task>()
    private var db: AppDatabase?=null
    private val binder = LocalBinder()
    inner class LocalBinder : Binder() {
        fun getService(): RunningService = this@RunningService
    }
    override fun onBind(intent: Intent?): IBinder? {
        Log.e(TAG, "onBind: bind service ", )
        return binder
    }

    override fun onCreate() {
        super.onCreate()
        Log.e(TAG, "onCreate: create sevice", )
        db?: run {
            db = Room.databaseBuilder(
                applicationContext,
                AppDatabase::class.java, "timetodo"
            ).build()
        }
        startForeground(runningTaskServiceId,
            createNotification(baseContext, runningServiceChannelId,
                "定时服务初始化完成", "点击添加定时任务",
                cls = MainActivity::class.java
            )
        )
        taskBroadcast = TaskReceiver()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            registerReceiver(taskBroadcast, IntentFilter(TimeToDoAction.ACTION_EXECUTE_TASK.name), RECEIVER_EXPORTED)
        }else{
            registerReceiver(taskBroadcast, IntentFilter(TimeToDoAction.ACTION_EXECUTE_TASK.name))
        }
        Log.d(TAG, "onCreate: stored tasks: ${taskList.toList()}")
        if(taskList.size==0){
            thread {
                db?.taskDao()?.getAll()?.let {
                    it.forEach {task->
                        if (runningFlag.contains(task.state)){
                            val offset = task.startTime+task.interval - System.currentTimeMillis()
                            if(offset>0){
                                updateRunningService(this, TaskType.valueOf(task.type), offset, task.taskId)
                            }else{
                                taskList.add(task.copy(state="已过期"))
                                syncTask()
                            }
                        }
                        Thread.sleep(100)
                    }
                }
            }
        }
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.e(TAG, "onStartCommand: start eerviceccc commande $intent")
        intent?.let {
            val interval = it.getLongExtra("interval", 0L)
            val taskType = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                it.getSerializableExtra("taskType", TaskType::class.java)?: TaskType.NONE
            } else {
                it.getSerializableExtra("taskType") as TaskType? ?: TaskType.NONE
            }
            when(taskType){
                TaskType.NONE->{}
                TaskType.STOP_SELF -> {
                    stopForeground(STOP_FOREGROUND_REMOVE)
                    return START_NOT_STICKY
                }
                else->{
                    var taskId = it.getLongExtra("taskId", 0L)
                    if (taskId == 0L) {
                        taskId = System.currentTimeMillis()
                    }
                    val task = appendTaskItemInfo(
                        taskType.name,
                        taskId,
                        getTipByTaskType(taskType), "定时 ${interval / 1000} s",
                        "进行中", interval
                    )
                    alarmTask(task)
                }
            }
        }
        val nearestTime = taskList.filter {
            runningFlag.contains(it.state)
        }.minByOrNull {
            it.endTime
        }?.endTime?: 0
        startForeground(runningTaskServiceId,
            createNotification(baseContext, runningServiceChannelId, "${runningTaskCount()}个任务执行中",
                if(nearestTime==0L) "点我添加定时任务"
                else "最近的Deadline:${nearestTime.timeFormat()}",
                cls = MainActivity::class.java
            )
        )
        return START_STICKY
    }

    private fun alarmTask(task: Task){
        Log.d(TAG, "alarmTask: $task")
        val interval = task.interval
        val taskType = task.type
        val taskId = task.taskId
        val action = when (TaskType.valueOf(taskType)) {
            TaskType.VIBRATE, TaskType.STOP_VIBRATE,
            TaskType.LIGHT_ON, TaskType.LIGHT_OFF,
            TaskType.LOCK_SCREEN -> TimeToDoAction.ACTION_EXECUTE_TASK.name
            else -> ""
        }

        fun action(){
            val runningFlag = getTaskState(taskId)
            Log.d(TAG, "action: action() $action $taskType ${task.state}/$runningFlag ${isTaskRunning(taskId)}")
            if(isTaskRunning(taskId)) {
                sendBroadcast(Intent(action).apply {
                    putExtra("state", taskType)
                })
                sendNotification(
                    this,
                    taskChannelId,
                    task.title,
                    "任务结束 创建于${taskId.timeFormat()}",
                    Intent(this, TaskDetailActivity::class.java).apply {
                        putExtra("taskId", taskId)
                    }
                )
                if (taskId != 0L) {
                    modifyTaskItemInfo(taskId, "已完成")
                }
            }
        }
        if(interval==0L){
            action()
        }else {
            val alarmManager = getSystemService(ComponentActivity.ALARM_SERVICE) as AlarmManager
            val triggerAtTime = System.currentTimeMillis() + interval
            alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerAtTime, "task", {
                action()
            }, null)
            showToast(this, "设置成功 $interval")
        }
    }
    private fun appendTaskItemInfo(name: String="", taskId: Long=0, title: String="",
                                   description: String="", state: String="", interval: Long=0,
                                   startTime: Long= currentTimestamp(), endTime: Long= timestampAfter(interval)
    ): Task{
        val task = Task(0, taskId, name, title, description, state,
            startTime, interval, endTime, currentTime(), currentTime())
        taskList.add(0, task)
        syncTask()
        return task
    }

    private fun syncTask() {
        thread {
            val dao = db!!.taskDao()
            taskList.forEach {task->
                dao.getAll().find{dbTask->
                    dbTask.taskId==task.taskId
                }?.let{
                    if(it.state!=task.state){
                        val newTask = task.copy(id=it.id)
                        dao.updateTaskState(newTask)
                    }
                }?:run {
                    dao.insert(task)
                }
            }
        }
    }

    fun modifyTaskItemInfo(taskId: Long, state: String){
        Log.d(TAG, "modifyTaskItemInfo: Modifier $taskId ${taskList.toList()}")
        for (info in taskList) {
            if(info.taskId == taskId){
                taskList[taskList.indexOf(info)] = info.copy(state=state, updateAt=currentTime())
                syncTask()
                break
            }
        }
        updateRunningService(this)
    }

    @Composable
    fun rememberTaskList(): State<List<Task>> {
        return rememberUpdatedState(taskList)
    }
    fun getTaskList(): List<Task> {
        return taskList
    }

    fun clearTaskList(){
        taskList.clear()
    }

    fun getTaskState(id: Long): String{
        for (info in taskList) {
            if(info.taskId == id){
                return info.state
            }
        }
        return ""
    }

    fun isTaskRunning(taskId: Long): Boolean {
        for (info in taskList) {
            if(info.taskId == taskId){
                return runningFlag.contains(info.state)
            }
        }
        return false
    }

    private fun runningTaskCount(): Int {
        var retTasks = 0
        Log.d(TAG, "runningTask: $taskList")
        taskList.forEach {
            if(runningFlag.contains(it.state)){
                ++retTasks
            }
        }
        return retTasks
    }

    private fun getTipByTaskType(taskType: TaskType): String{
        return when(taskType){
            TaskType.LIGHT_ON->"定时打开手电筒"
            TaskType.LIGHT_OFF->"定时关闭手电筒"
            TaskType.LOCK_SCREEN->"定时锁定屏幕"
            TaskType.VIBRATE->"定时震动"
            TaskType.STOP_VIBRATE->"定时停止震动"
            else->""
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.e(TAG, "onDestroy: servcice destoryed", )
        taskBroadcast?.let {
            unregisterReceiver(taskBroadcast)
            taskBroadcast = null
        }
//        stopSelf()
//        removeAllNotification(this)
//        removeNotification(this, runningServiceChannelId)
    }

    override fun stopService(name: Intent?): Boolean {
        Log.d(TAG, "stopService: ")
        return super.stopService(name)
    }
}

private val TAG = "[RunningService "
fun updateRunningService(context: Context, taskType: TaskType = TaskType.NONE, interval: Long=0, taskId: Long=0){
    Log.d(TAG, "updateRunningService: $interval $taskType")
    context.startService(Intent(context, RunningService::class.java).apply {
        putExtra("interval", interval)
        putExtra("taskType", taskType)
        putExtra("taskId", taskId)
    })
}

fun stopRunningService(context: Context){
    Log.d(TAG, "stopRunningService: ")
//    context.stopService(Intent(context, RunningService::class.java))
//    context.for(Intent(context, RunningService::class.java))
//    removeAllNotification(context)
    updateRunningService(context, TaskType.STOP_SELF)
}